﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ensemble;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.ServiceModel.Web;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace TicketSeller
{
    class TicketSellerHost
    {
        public const int FLIGHT_NUMBER_IDX   = 0;

        public const int SOURCE_IDX          = 1;

        public const int DESTINATION_IDX     = 2;

        public const int DATE_IDX            = 3;

        public const int NODE_NAME_PARAM     = 0;

        public const int NODE_ALLIANCE_PARAM = 1;

        public const int NODE_PORT_PARAM     = 2;

        public const int SEARCH_SERVER_PARAM = 3;

        public const int INPUT_FILE_PARAM    = 4;

        static void Main(string[] args)
        {
            if (args.Length != 5)
            {
                Console.WriteLine( "Incorrect input parameters format.");
                Console.WriteLine( "Expecting: <name> <alliance> <port> <search server> <input>");
                return;
            }

            string fileName = args[INPUT_FILE_PARAM];

            if (!File.Exists(fileName))
            {
                Console.WriteLine( "Error. Could not find input file: {0}.", fileName);
                return;
            }

            Console.WriteLine( "Tickets seller {0}", args[NODE_NAME_PARAM]);
            Console.WriteLine("Press any key to start");
            Console.ReadLine();

            StreamReader reader = new StreamReader( fileName);
            string line = null;
            int lineNumber = 0;
            // Read and parse the data from the file.
            while (( line = reader.ReadLine()) != null)
            {
                ++lineNumber;
                string[] data = line.Split(' ');
                if (data.Length != 4)
                {
                    Console.WriteLine( "Could not parse line number: ()", lineNumber);
                    continue;
                }
                string flightNumber = data[FLIGHT_NUMBER_IDX];
                string source = data[SOURCE_IDX];
                string destination = data[DESTINATION_IDX];
                string date = data[DATE_IDX];
                Ticket ticket = new Ticket( );
                ticket.date = date;
                ticket.source = source;
                ticket.destination = destination;
                ticket.flightNo = flightNumber;
                ticket.airCarrier = args[NODE_NAME_PARAM];
                ticket.alliance = args[NODE_ALLIANCE_PARAM];
                TicketsDB.Instance.insertTicket( ticket);
                Console.WriteLine( "{0} {1} {2} {3} {4}", date, source, destination, flightNumber, args[NODE_NAME_PARAM]);
            }
            // Initialize cluster ensemble communicator
            int trial = 3;
            Thread ensembleThread = null;
            while (trial > 0)
            {
                try
                {
                    Console.WriteLine( "Trying to register at flight search server.");
                    ClusterCommunicator communicator = new ClusterCommunicator(args[NODE_NAME_PARAM], args[NODE_ALLIANCE_PARAM],
                        args[SEARCH_SERVER_PARAM], Convert.ToInt32(args[NODE_PORT_PARAM]));
                    ensembleThread = new Thread(new ThreadStart(communicator.serveCommunication));
                    ensembleThread.Start();
                    break;
                }
                catch (RegistrationServerDown e)
                {
                    trial--;
                    Thread.Sleep(100);
                    Console.WriteLine( "Flight search server is not available. Will try {0} more times", trial);
                }
            }
            if (trial == 0)
            {
                Console.WriteLine( "Didn't succeeded to register at flight search server. Exiting.");
                return;
            }


            using (ServiceHost host = new ServiceHost(typeof(TicketsFinderService),
                        new Uri("http://localhost:" + args[NODE_PORT_PARAM] + "/FlightSearch/" + args[NODE_NAME_PARAM])))
            {
                Console.WriteLine( String.Format( "Flight search server of vendor {0} from alliance {1} starting...", args[NODE_NAME_PARAM], args[NODE_ALLIANCE_PARAM]));
                foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
                {
                    Console.WriteLine( "Endpoint ({0}) registered listening at address: {1}", endpoint.Name, endpoint.Address);
                }
                host.Open();
                Console.WriteLine("Press any key to stop node from running...");
                Console.ReadLine();
            }
            if ( ensembleThread != null)
                ensembleThread.Abort();
        }
    }
}